﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using CSW.Framework.Common;
using CSW.Framework.Common.Binding.Interfaces;

namespace CSW.Framework.UI
{
    /// <summary>
    /// In-place Edit Grid Controller.  Type safe access to <see cref="DataGridView" />.
    /// </summary>
    /// <typeparam name="T">The business object item.</typeparam>
    public class InplaceEditDataGridViewController<T> : TypedDataGridViewController<T>
        where T : class, IBusinessObject
    {
        private BindingList<T> m_PreviousDataSource;

        /// <summary>
        /// Initializes a new instance of the <see cref="InplaceEditDataGridViewController{T}"/> class.
        /// </summary>
        /// <param name="dataGridView">The grid control.</param>
        public InplaceEditDataGridViewController(DataGridView dataGridView)
            : this(dataGridView, true)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="InplaceEditDataGridViewController{T}"/> class.
        /// </summary>
        /// <param name="dataGridView">The grid control.</param>
        /// <param name="multiSelect">if set to <c>true</c>, multi select is enabled (default = true).</param>
        public InplaceEditDataGridViewController(DataGridView dataGridView, bool multiSelect)
            : base(dataGridView, multiSelect)
        {
            DataGridView.ReadOnly = false;
            DataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect;
            DataGridView.TabStop = true;
            dataGridView.EditMode = DataGridViewEditMode.EditOnEnter;

            DataGridView.DataSourceChanged += m_GridView_DataSourceChanged;
            HookDataSource();
        }

        /// <summary>
        /// Makes the grid editable.  Uses the embedded navigator.
        /// </summary>
        /// <param name="allowAppend">if set to <c>true</c>, adds an append button.</param>
        /// <param name="allowRemove">if set to <c>true</c>, adds a remove button.</param>
        public void Setup(bool allowAppend, bool allowRemove)
        {
            if (allowAppend)
            {
                DataGridView.AllowUserToAddRows = false;
            }

            if (allowRemove)
            {
                DataGridView.AllowUserToDeleteRows = false;

                /*if (handleRemove)
                {
                    Grid.EmbeddedNavigator.ButtonClick += EmbeddedNavigator_RemoveButtonClick;
                }*/
            }
        }

        private void m_GridView_DataSourceChanged(object sender, EventArgs e)
        {
            HookDataSource();
        }

        private void HookDataSource()
        {
            if (m_PreviousDataSource != null)
                m_PreviousDataSource.ListChanged -= DataSource_ListChanged;

            if (DataSource != null)
                DataSource.ListChanged += DataSource_ListChanged;

            m_PreviousDataSource = DataSource;
        }

        private void DataSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            if (e.ListChangedType == ListChangedType.ItemAdded)
            {
                IBusinessObject businessObject = DataSource[e.NewIndex];
                if (!businessObject.IsEditting)
                    businessObject.BeginEdit();
            }
        }

        /*private void EmbeddedNavigator_RemoveButtonClick(object sender, NavigatorButtonClickEventArgs e)
        {
            if (e.Button.ButtonType == NavigatorButtonType.Remove)
            {
                DialogResult result = MessageBox.Show("Remove selected record(s)?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                GridView.CloseEditor();
                if (result != DialogResult.Yes)
                {
                    e.Handled = true;
                }
                else
                {
                    GridView.CloseEditor();
                    GridView.UpdateCurrentRow();
                }
            }
        }*/

        /*/// <summary>
        /// Sets the data source from a list of objects which implement <see cref="IGetBusinessObject{T}"/>.
        /// </summary>
        /// <typeparam name="U">The type which implements <see cref="IGetBusinessObject{T}"/>.</typeparam>
        /// <param name="list">The list.</param>
        public void SetDataSource<U>(IEnumerable<U> list)
            where U : IGetBusinessObject<T>
        {
            Guard.ArgumentNotNull(list, "list");

            BindingList<T> newList = new BindingList<T>();
            foreach (U item in list)
            {
                T newItem = item.RawBusinessObject;
                if (newItem == null)
                {
                    newItem = item.GetBusinessObject();
                    newItem.BeginEdit(false);
                }
                else
                {
                    if (!newItem.IsEditting)
                        newItem.BeginEdit(true);
                }

                newList.Add(newItem);
            }

            DataSource = newList;
        }*/

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public override void Dispose()
        {
            DataGridView.DataSourceChanged -= m_GridView_DataSourceChanged;

            base.Dispose();
        }
    }
}
